﻿using System;
using System.Collections.Generic;
using CiStatus.CiStatusAddIn.Logic.Exceptions;
using CiStatus.CiStatusAddIn.Logic.PluginInterfaces;
using CiStatus.CiStatusAddIn.Logic.Status;
using ThoughtWorks.CruiseControl.CCTrayLib.Configuration;
using ThoughtWorks.CruiseControl.CCTrayLib.Monitoring;
using ThoughtWorks.CruiseControl.Remote;


namespace CCNet157
{
    public class CcNetPoller : ICiPoller
    {
    	private readonly IDictionary<string, ICiPollerParameter> _parameters;
        private ICruiseServerManager _manager;
        private BuildServer _buildServer;
        private CruiseServerManagerFactory _cruiseServerManagerFactory;

    	public CcNetPoller(IDictionary<string, ICiPollerParameter> parameters)
    	{
    		_parameters = parameters;
    	}

    	public void Connect()
        {
            _buildServer = BuildServer.BuildFromRemotingDisplayName(_parameters["Server"].Value);
            ICruiseServerClientFactory remoteCruiseManagerFactory = new CruiseServerClientFactory();
            _cruiseServerManagerFactory = new CruiseServerManagerFactory(remoteCruiseManagerFactory);
        }

    	public IDictionary<string, ICiPollerParameter> Parameters
    	{
    		get { return _parameters; }
    	}

    	public IStatus CurrentStatus()
        {
            try
            {
                _manager = _cruiseServerManagerFactory.Create(_buildServer);

                IStatus status = new StatusOffline(new StatusDetails { Message = "Offline" });
                var projectStatus = GetProjects();

                status = CheckBuildStatus(projectStatus, status);
                //status = CheckProjectStatus(projectStatus, status);

                return status; 
            }
            catch (Exception e)
            {
               throw new CommunicationPollerException(e.Message, e);
            }
        }

        private IStatus CheckBuildStatus(ProjectStatus projectStatus, IStatus status)
        {
            var activity = projectStatus.Activity;

            var estimatedTime = projectStatus.NextBuildTime.Subtract(projectStatus.LastBuildDate).TotalSeconds;
            var duration = DateTime.Now.Subtract(projectStatus.NextBuildTime).TotalSeconds;

            var details = new StatusDetails
                              {
                                  Activity = activity.Type,
                                  BuildLabel = projectStatus.LastBuildLabel,
                                  BuildTime = projectStatus.LastBuildDate,
                                  Details = projectStatus.CurrentMessage,
                                  BuildStatus = projectStatus.Status.ToString(),
                                  Progress = new Progress(estimatedTime, duration)
                              };

            switch (projectStatus.BuildStatus)
            {
                case IntegrationStatus.Failure:
                    details.Message = "Failed";
                    status = new StatusFailed(details);
                    break;
                case IntegrationStatus.Success:
                    details.Message = "Success";
                    status = new StatusSuccess(details);
                    break;
            }
            
            if (activity.IsBuilding())
            {
                details.Message = "Building...";
                status = new StatusBuilding(details);
            }
            
            return status;
        }

        private ProjectStatus GetProjects()
        {
            var snapshot = _manager.GetCruiseServerSnapshot();
			return snapshot.GetProjectStatus(_parameters["Project"].Value);
        }
    }
}
